package com.springboot.codeminestarter.codemine.aop.log;

import com.springboot.codeminestarter.codemine.business.log.dao.LogWrapperDao;
import com.springboot.codeminestarter.codemine.business.log.domain.LogRecord;
import com.springboot.codeminestarter.codemine.utils.UUIDUtil;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.annotation.Order;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

import javax.annotation.Resource;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;

@Aspect
@Component
@Order(1)
public class LogWriteWrapper {

    private static final Logger LOGGER = LoggerFactory.getLogger(LogWriteWrapper.class);

    @Resource
    private LogWrapperDao logWrapperDao;

    @Resource
    private PlatformTransactionManager transactionManager;

    @Pointcut(value = "@annotation(com.springboot.codeminestarter.codemine.aop.log.LogWrite)")
    private void pointCut() {

    }

    @Before(value = "pointCut()")
    public void logWrite(JoinPoint point) {

        handleLog(point);
    }

    private void handleLog(JoinPoint point) {

        LOGGER.info(">>>>>>>>LogWrite Aspect Wrapper Start.<<<<<<<<");
        MethodSignature signature = (MethodSignature) point.getSignature();
        Class returnType = signature.getReturnType();
        LOGGER.info("ReturnType is {}", returnType);

        Method method = signature.getMethod();
        LogWrite annotation = method.getAnnotation(LogWrite.class);
        String value = annotation.value();
        LOGGER.info("LogWrite Annotation Value is {}", value);

        Annotation[] declaredAnnotations = method.getDeclaredAnnotations();
        for (Annotation declaredAnnotation : declaredAnnotations) {
            if (declaredAnnotation instanceof GetMapping) {
                LOGGER.info("GetMapping Annotation Value is {}", declaredAnnotation);
            } else if (declaredAnnotation instanceof PostMapping) {
                LOGGER.info("PostMapping Annotation Value is {}", declaredAnnotation);
            }
            LOGGER.info("declaredAnnotation is {}", declaredAnnotation.annotationType().getName());
        }
        LogRecord logRecord = new LogRecord();
        logRecord.setId(UUIDUtil.uuid());
        logRecord.setContent(value);
        logRecord.setOperateType("INSERT");
        logRecord.setUserId("000000");
        logRecord.setUserName("codemine");
        writeLogWrapper(logRecord);
        LOGGER.info(">>>>>>>>LogWrite Aspect Wrapper End.<<<<<<<<");
    }

    @Async
    public void writeLogWrapper(LogRecord logRecord) {
        TransactionStatus transaction = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            logWrapperDao.addLogWrapper(logRecord);
            transactionManager.commit(transaction);
        } catch (Exception e) {
            LOGGER.error("异步日志入库异常");
            transactionManager.rollback(transaction);
        }
    }
}
